/*
* File: webserver.c
* Version: 1.0
* Last modified on Fri Mars 07 2014 by group 5
* Members:
* Johan Forsblom, Johanna Carlsson, Dragana Todorovic, 
* Hampus Herbertsson, Robin Henriksson
* -----------------------------------------------------
* This file implements the webserver.h interface.
*/

#include <winsock2.h> 
#include <Ws2tcpip.h>
#include <stdio.h>
#include <process.h>
#include "webserver.h"
#include "http_parser.h"
#include "handleTelnet.h"
#include "logfile.h"
#include "configFile.h"


/* Constants */
#define BUFFER_SIZE	512

/* struct for serverData */
typedef struct{
	SOCKET serverSocket;
}serverDataT;

/* static global variables */
static serverDataT serverCon;
static int serverStatus = SERVER_ACTIVE;

static void printInfo();


/* Main program */
int main()
{
	WSADATA wsaData; 
	WORD wVersionRequested = MAKEWORD( 2, 2 );
	struct sockaddr clientAddr;
	int clientAddrLen;
	char hostName[100]; 
	char portName[100];
	
	int err = WSAStartup( wVersionRequested, &wsaData );

	int done=0;
	SOCKET clientSocket;	
	loadConfigFile();
	
    printInfo();
	printConfigFile();
	/* start the serversocket */
	startServerSocket(&serverCon.serverSocket);	

	/* start the telnet thread */
	if (_beginthread(startTelnetThread, BUFFER_SIZE, NULL) < 0){
		printf("ERROR: Could not create thread to handle parsing!\n");
		system("pause");
		exit(1);
	}

	printf("\nServer Running, waiting for connections\n");
	while(!done) {			
		clientAddrLen = sizeof(clientAddr);
		clientSocket = accept(serverCon.serverSocket, &clientAddr, &clientAddrLen); 

		if(serverStatus == SERVER_ACTIVE){
			//check if the socket is valid
			if(clientSocket != INVALID_SOCKET && serverCon.serverSocket!= SOCKET_ERROR) {
				parDataT *parData = (parDataT*)malloc(sizeof (parDataT));				

				/* get info about the connecting client */
				int ok = getnameinfo(&clientAddr, clientAddrLen, hostName, 100,portName, 100, NI_NUMERICSERV ); 

				/* print out who is connecting */
				if(ok == 0) {
					sprintf(parData->hostName, "%s",hostName);
					parData->clientSocket = clientSocket;
					printf("Accept incoming from: %s at port %s\n",hostName,portName);
					printf("starting a new thread!\n");
					if (_beginthread(parseHTTP, BUFFER_SIZE, (void *)parData) < 0) {
						printf("ERROR: Could not create thread to handle parsing!\n");
						system("pause");
						exit(1);
					}
				}
			} 
			else {
				printf("Could not create socket!\n");
				system("pause");
			}
		}else
			closesocket(clientSocket);					
	}
	getchar();
	WSACleanup();
}


/* Function: startServerSocket
* usage: startServerSocket(serverSocket);
* ----------------------------------------------------------------
* This function creats a new server socket, binds the port and listens to incomming
* connections.
*/
void startServerSocket(SOCKET *serverSocket)
{
	struct addrinfo *info;
	int ok;	
	char serverPort[10];
	getServerPort(serverPort);
	serverCon.serverSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

	if (serverCon.serverSocket < 0) {
		printf("ERROR: server socket failed\n");
		system("pause");
		exit(1);
	}

	if (serverSocket < 0) {
		printf("ERROR: server socket failed\n");
		system("pause");
		exit(1);
	}

	ok = getaddrinfo("localhost", serverPort ,NULL, &info);

	if(ok !=0) {
		WCHAR * error = gai_strerror(ok);
		printf("%s\n",error);
		system("pause");
	}
	else{ 
		while(info->ai_family != AF_INET && info->ai_next != NULL)
			info = info->ai_next;
	}

	ok = bind(*serverSocket, info->ai_addr, info->ai_addrlen);
	if(ok == SOCKET_ERROR) {
		int err = WSAGetLastError();
		printf("%d\n",err);
		system("pause");
		exit(1);
	}

	ok = listen(*serverSocket, SOMAXCONN );
	if(ok == SOCKET_ERROR) {
		int err = WSAGetLastError();
		printf("%d\n",err);
		system("pause");
		exit(1);
	}
}


/* Function: closeServerSocket
* usage: closeServerSocket(clientSocket);
* ----------------------------------------------------------------
* This function closes the serversocket.
*/
void closeServerSocket(SOCKET *serverSocket)
{
	closesocket(*serverSocket);
}


/* Function: getServerSocket
* usage: socket = getServerSocket(clientSocket);
* ----------------------------------------------------------------
* This function returns the current serversocket.
*/
SOCKET* getServerSocket()
{
	return &serverCon.serverSocket;
}


/* Function: getServerStatus
* usage: getServerStatus();
* ----------------------------------------------------------------
* This function returns the current server status. Active or inactive.
*/
int getServerStatus()
{	
	return serverStatus;
}


/* Function: setServerStatus
* usage: setServerStatus(status);
* ----------------------------------------------------------------
* This function sets the server status.
*/
void setServerStatus(int status)
{	
	if(status == SERVER_INACTIVE || status == SERVER_ACTIVE)
		serverStatus = status;
	else
		printf("invalid serverstatus");
}

static void printInfo()
{
    printf("Lab 1 Datakommunikation - Webserver\n\n");
    printf("Members:\n");
    printf("--------\n");
    printf("Johan Forsblom\nJohanna Carlsson\nDragana Todorovic\nHampus Herbertsson\nRobin Henriksson\n\n");
}



